//
// Created by yanhai on 2021/11/5.
//

// 上一个hashtable是基于模板方式实现的，
// 这个是定义好了2个基类，用于继承基类就可以使用这个hash了。

#pragma once

#include <mutex>
#include <functional>
#include <cassert>

// value的基类
struct HashTableThreadValue {
    // 获取hash函数
    virtual unsigned int Hash() = 0;
};

// 节点的基类
struct HashTableThreadBucketNode {
    // 和 HashTableThreadValue 比较函数
    virtual bool CompareValue(HashTableThreadValue *v) = 0;
    // 根据value来初始化node节点
    virtual void InitByValue(HashTableThreadValue *v) = 0;

    // 用在hash中
    HashTableThreadBucketNode *hnext{nullptr};

    // 用在共享队列中
    HashTableThreadBucketNode *lprev{nullptr};
    HashTableThreadBucketNode *lnext{nullptr};

    // 锁 todo 锁的类型由用户决定：比如可以使用 mutex 或者 spinlock
    std::mutex mutex;
};

// 桶结构，节点头指针和一个锁
/* hash bucket structure */
struct HashTableThreadBucket {
    // 节点头指针
    HashTableThreadBucketNode *head{nullptr};

    // 锁 todo 锁的类型由用户决定：比如可以使用 mutex 或者 spinlock
    std::mutex mutex;
};

// hash管理类
class HashTableThread {
public:
    typedef HashTableThreadBucketNode *node_type;
    typedef HashTableThreadValue *value_type;

    HashTableThread(unsigned int size,
//                    const std::function<unsigned int(node_type)> &hash,
//                    const std::function<bool(node_type, value_type)> &compare,
                    const std::function<node_type(void)> &NewNode,
//                    const std::function<void(node_type, value_type)> &InitNode,
                    const std::function<void(node_type)> &FreeNode)
            : array_size(size),
//              hash(hash),
//              compare(compare),
              NewNode(NewNode),
//              InitNode(InitNode),
              FreeNode(FreeNode)
    {
        assert(array_size > 0);
        array = new HashTableThreadBucket[array_size];
    }

    ~HashTableThread()
    {
        delete[] array;
    }

    // 根据v查找对应的node节点
    // 如果不存在，则申请一个node节点并放入hash
    // 如果申请失败，则返回null
    node_type Find(value_type v);

    // 超时清理节点，并执行回调函数
    bool CheckTimeout(std::time_t now,
                      const std::function<bool(node_type, std::time_t)> &IsTimeout,
                      const std::function<void(node_type)> &CallBack);

private:
    // 一些回调函数
//    const std::function<unsigned int(node_type)> &hash;  // 计算hash值
//    const std::function<bool(node_type, value_type)> &compare; // 比较函数
    const std::function<node_type(void)> &NewNode;  // 获取一个新的节点
//    const std::function<void(node_type, value_type)> &InitNode;  // 根据value来初始化node节点
    const std::function<void(node_type)> &FreeNode;   // 释放一个节点

    // 桶和桶大小
    const unsigned int array_size;
    HashTableThreadBucket *array;
};
